package com.orderplus.opshop.synces.service.product.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.orderplus.opshop.common.util.MapUtil;
import com.orderplus.opshop.common.util.ValueUtil;
import com.orderplus.opshop.core.data.request.RequestParam;
import com.orderplus.opshop.core.data.response.ResponseData;
import com.orderplus.opshop.synces.bean.ProductDetailModel;
import com.orderplus.opshop.synces.constant.EsConstant;
import com.orderplus.opshop.synces.entity.product.ProductPropertyList;
import com.orderplus.opshop.synces.mapper.product.IProductMapper;
import com.orderplus.opshop.synces.mapper.product.IProductPropertyListMapper;
import com.orderplus.opshop.synces.mapper.product.IProductPropertyMapper;
import com.orderplus.opshop.synces.service.elasticsearch.data.QueryParamData;
import com.orderplus.opshop.synces.service.elasticsearch.data.QueryResultData;
import com.orderplus.opshop.synces.service.elasticsearch.impl.OpSearchService;
import com.orderplus.opshop.synces.service.product.ProductPropertyListService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * remark
 *
 * @author mhj
 * @date 2019-04-22 11:20:14
 */
@Service("productPropertyListService")
public class ProductPropertyListServiceImpl extends ServiceImpl<IProductPropertyListMapper, ProductPropertyList> implements ProductPropertyListService {
	@Resource
	private IProductMapper iProductMapper;
	@Resource
	private IProductPropertyMapper iProductPropertyMapper;

	@Autowired
	private OpSearchService opSearchService;

	@Override
	public List<ProductDetailModel> mapFromProductPropertyListToProductDetailModel(Map<String, Object> map, String action, List<ProductDetailModel> productDetailModelList) {
		try {
//			把表名的字段名中包含_替换
			Map<String, Object> newMap = MapUtil.assemble(map);

//			转成product表的数据
			ProductPropertyList productPropertyList = (ProductPropertyList) MapUtil.mapToObject(newMap, ProductPropertyList.class);

			ProductDetailModel.ProductProperty.PropsValue propsValue = setData(productPropertyList, action);

//			query key 格式: propList..propValueList.valueId
//			String queryKey = new StringBuffer("propertyListSrc.propValueList.valueId").toString();
			String queryKey = new StringBuffer("propertyListIds.propValueList.valueId").toString();

			List<Map<String, Object>> queryResult = queryProductPropValue(propsValue, queryKey);

			if (ValueUtil.isNotEmpty(queryResult)) {
				for (Map<String, Object> getMap : queryResult) {
					List<Map<String, Object>> propList = (List<Map<String, Object>>) getMap.get("propertyListIds");

					if (ValueUtil.isNotEmpty(propList)) {
						for (Map<String, Object> productPropertyMap : propList) {
							ProductDetailModel.ProductProperty productProps = mapToProductProperty(productPropertyMap);

							ProductDetailModel productDetailModel = new ProductDetailModel();

							String productId = ValueUtil.toStr(getMap.get(EsConstant.ES_PRIMARY_KEY));
							productDetailModel.setProductId(productId);

							List<ProductDetailModel.ProductProperty.PropsValue> propertyValueList = new LinkedList<>();

							if (ValueUtil.isNotEmpty(productProps.getPropValueList())) {
								for (ProductDetailModel.ProductProperty.PropsValue value : productProps.getPropValueList()) {
									if (ValueUtil.equals(value.getValueId(), propsValue.getValueId())) {
										propsValue = copyValueData(value, propsValue);
									}
								}
							}

							propertyValueList.add(propsValue);
							productProps.setPropValueList(propertyValueList);

							List<ProductDetailModel.ProductProperty> propertyList = new LinkedList<>();
							propertyList.add(productProps);
//							productDetailModel.setPropertyListSrc(propertyList);
							productDetailModel.setPropertyListIds(propertyList);

							productDetailModelList.add(productDetailModel);
						}
					}
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

		return productDetailModelList;
	}

	private ProductDetailModel.ProductProperty copyKeyData(ProductDetailModel.ProductProperty oldProps, ProductDetailModel.ProductProperty targetProps) {
		if (ValueUtil.isEmpty(targetProps.getPropId())) {
			targetProps.setPropId(oldProps.getPropId());
		}
		if (ValueUtil.isEmpty(targetProps.getPropKey())) {
			targetProps.setPropKey(oldProps.getPropKey());
		}
		if (ValueUtil.isEmpty(targetProps.getPropKeyId())) {
			targetProps.setPropKeyId(oldProps.getPropKeyId());
		}
		if (ValueUtil.isEmpty(targetProps.getPropKeyTh())) {
			targetProps.setPropKeyTh(oldProps.getPropKeyTh());
		}
		if (ValueUtil.isEmpty(targetProps.getPropKeyZh())) {
			targetProps.setPropKeyZh(oldProps.getPropKeyZh());
		}

		return targetProps;
	}

	private ProductDetailModel.ProductProperty.PropsValue copyValueData(ProductDetailModel.ProductProperty.PropsValue oldPropsValue, ProductDetailModel.ProductProperty.PropsValue targetPropsValue) {
		if (ValueUtil.isEmpty(targetPropsValue.getPropId())) {
			targetPropsValue.setPropId(oldPropsValue.getPropId());
		}
		if (ValueUtil.isEmpty(targetPropsValue.getPropValue())) {
			targetPropsValue.setPropValue(oldPropsValue.getPropValue());
		}
		if (ValueUtil.isEmpty(targetPropsValue.getPropValueId())) {
			targetPropsValue.setPropValueId(oldPropsValue.getPropValueId());
		}
		if (ValueUtil.isEmpty(targetPropsValue.getPropValueTh())) {
			targetPropsValue.setPropValueTh(oldPropsValue.getPropValueTh());
		}
		if (ValueUtil.isEmpty(targetPropsValue.getPropValueZh())) {
			targetPropsValue.setPropValueZh(oldPropsValue.getPropValueZh());
		}

		return targetPropsValue;
	}

	@Override
	public ProductDetailModel.ProductProperty mapToProductProperty(Map<String, Object> productPropertyMap) {
		ProductDetailModel.ProductProperty productProperty = new ProductDetailModel.ProductProperty();

		productProperty.setPropId(ValueUtil.toStr(productPropertyMap.get("propId")));
		productProperty.setPropKey(ValueUtil.toStr(productPropertyMap.get("propKey")));
		productProperty.setPropKeyZh(ValueUtil.toStr(productPropertyMap.get("propKeyZh")));
		productProperty.setPropKeyTh(ValueUtil.toStr(productPropertyMap.get("propKeyTh")));
		productProperty.setPropKeyId(ValueUtil.toStr(productPropertyMap.get("propKeyId")));

		List<Map<String, Object>> valueList = (List<Map<String, Object>>) productPropertyMap.get("propValueList");
		List<ProductDetailModel.ProductProperty.PropsValue> propValueList = new LinkedList<>();

		if (ValueUtil.isNotEmpty(valueList)) {
			for (Map<String, Object> map : valueList) {
				ProductDetailModel.ProductProperty.PropsValue propsValue = mapToPropsValue(map);
				propValueList.add(propsValue);
			}
			productProperty.setPropValueList(propValueList);
		}

		return productProperty;
	}

	@Override
	public ProductDetailModel.ProductProperty.PropsValue mapToPropsValue(Map<String, Object> productPropertyMap) {
		ProductDetailModel.ProductProperty.PropsValue propsValue = new ProductDetailModel.ProductProperty.PropsValue();

		propsValue.setValueId(ValueUtil.toStr(productPropertyMap.get("valueId")));
		propsValue.setPropId(ValueUtil.toStr(productPropertyMap.get("propId")));
		propsValue.setPropValue(ValueUtil.toStr(productPropertyMap.get("propValue")));
		propsValue.setPropValueZh(ValueUtil.toStr(productPropertyMap.get("propValueZh")));
		propsValue.setPropValueTh(ValueUtil.toStr(productPropertyMap.get("propValueTh")));
		propsValue.setPropValueId(ValueUtil.toStr(productPropertyMap.get("propValueId")));

		return propsValue;
	}

	private ProductDetailModel.ProductProperty.PropsValue setData(ProductPropertyList productPropertyList, String action) {
		ProductDetailModel.ProductProperty.PropsValue propsValue = new ProductDetailModel.ProductProperty.PropsValue();

		if (ValueUtil.isNotEmpty(productPropertyList.getId())) {
			propsValue.setValueId(ValueUtil.toStr(productPropertyList.getId()));
		}
		if (ValueUtil.isNotEmpty(productPropertyList.getPropertyId())) {
			propsValue.setPropId(ValueUtil.toStr(productPropertyList.getPropertyId()));
		}

//		if ("update".equals(action)) {
		if (ValueUtil.isNotEmpty(productPropertyList.getPropertyValue())) {
			propsValue.setPropValue(productPropertyList.getPropertyValue());
		}
		if (ValueUtil.isNotEmpty(productPropertyList.getPropertyValueId())) {
			propsValue.setPropValueId(productPropertyList.getPropertyValueId());
		}
		if (ValueUtil.isNotEmpty(productPropertyList.getPropertyValueTh())) {
			propsValue.setPropValueTh(productPropertyList.getPropertyValueTh());
		}
		if (ValueUtil.isNotEmpty(productPropertyList.getPropertyValueZh())) {
			propsValue.setPropValueZh(productPropertyList.getPropertyValueZh());
		}
//		} else {
//			propsValue.setPropValue(null);
//			propsValue.setPropValueId(null);
//			propsValue.setPropValueTh(null);
//			propsValue.setPropValueZh(null);
//		}

		return propsValue;
	}

	private List<Map<String, Object>> queryProductPropValue(ProductDetailModel.ProductProperty.PropsValue propsValue, String queryKey) throws IOException {
		List<Map<String, Object>> result = new ArrayList<>();

//		int count = opSearchService.queryTotal(EsConstant.ES_INDICES, new String[]{queryKey}, new String[]{propsValue.getValueId()});

//		int pages = 0;
//		int size = 1000;
//		if (count % size == 0) {
//			pages = count / size;
//		} else {
//			pages = count / size + 1;
//		}
//		for (int i = 0; i < pages; i++) {
//			RequestParam<QueryParamData> request = opSearchService.setDefaultParam(EsConstant.ES_INDICES, new String[]{queryKey}, new String[]{propsValue.getValueId()}, i, size);
		RequestParam<QueryParamData> request = opSearchService.setDefaultParam(EsConstant.ES_INDICES, new String[]{queryKey}, new String[]{propsValue.getValueId()}, 0, 5000);

		ResponseData<QueryResultData.ListQueryResultData> response = opSearchService.call(request);

		result.addAll(response.getData().getResultDetailList());
//		}

		return result;
	}

	@Override
	public ProductDetailModel.ProductProperty.PropsValue convertPropListIdsToMapObject(String propListId, String action) {
		if (ValueUtil.isEmpty(propListId)) {
			return null;
		}

		ProductPropertyList productPropertyList = baseMapper.selectById(propListId);

		if (null != productPropertyList) {
			ProductDetailModel.ProductProperty.PropsValue productPropsValue = setData(productPropertyList, action);

			return productPropsValue;
		}

		return null;
	}

	@Override
	public List<ProductDetailModel.ProductProperty> convertMapToPropsList(List<Map<String, Object>> propertyListIdList, String action, ProductDetailModel.ProductProperty productProps) {
		List<ProductDetailModel.ProductProperty> propList = new LinkedList<>();

		if (ValueUtil.isNotEmpty(propertyListIdList)) {
			for (Map<String, Object> propertyListIdMap : propertyListIdList) {
				ProductDetailModel.ProductProperty productProperty = mapToProductProperty(propertyListIdMap);

				if (ValueUtil.equals(productProperty.getPropId(), productProps.getPropId())) {
					copyKeyData(productProperty,productProps);
					propList.add(productProps);
				}
			}
		}

		return propList;
	}

	@Override
	public List<ProductDetailModel.ProductProperty.PropsValue> convertMapToPropsValue(List<Map<String, Object>> propValueMapList, String action)
			throws IllegalAccessException, InvocationTargetException, InstantiationException {
		List<ProductDetailModel.ProductProperty.PropsValue> propValueList = new LinkedList<>();

		if (ValueUtil.isNotEmpty(propValueMapList)) {
			for (Map<String, Object> propValueMap : propValueMapList) {
				ProductPropertyList productPropertyList = (ProductPropertyList) MapUtil.mapToObject(propValueMap, ProductPropertyList.class);

				ProductDetailModel.ProductProperty.PropsValue propsValue = setData(productPropertyList, action);

				propValueList.add(propsValue);
			}
		}

		return propValueList;
	}

	@Override
	public IPage<Map<String, Object>> pageMap(Page<Map<String, Object>> page) {
		return baseMapper.pageMap(page);
	}

	private List<Map<String, Object>> queryProductPropValueMaps(String id) {
		List<Map<String, Object>> result = new ArrayList<>();

		QueryWrapper queryWrapper = new QueryWrapper();

		queryWrapper.eq("id", id);

		result = baseMapper.selectMaps(queryWrapper);

		return result;
	}

	@Override
	public List<ProductDetailModel> queryProductPropertyListToProductDetailModel(Map<String, Object> map, String action, List<ProductDetailModel> productDetailModelList)
			throws IllegalAccessException, InstantiationException, InvocationTargetException, IOException {
		String id = ValueUtil.toStr(map.get("id"));
		ProductDetailModel.ProductProperty.PropsValue propsValue = new ProductDetailModel.ProductProperty.PropsValue();

		propsValue.setValueId(id);

		String queryKey = new StringBuffer("propertyListIds.propValueList.valueId").toString();

		List<Map<String, Object>> maps = queryProductPropValue(propsValue, queryKey);

		if (ValueUtil.isNotEmpty(maps)) {
			for (Map<String, Object> queryMap : maps) {
				String productId = ValueUtil.toStr(queryMap.get("productId"));

				List propertyListIds = (List) queryMap.get("propertyListIds");

				List<ProductDetailModel.ProductProperty> productPropertyList = new LinkedList<>();
				for (int i = 0; i < propertyListIds.size(); i++) {
					Map propertyListIdsMap = (Map) propertyListIds.get(i);

					Map propValueMap = (Map) propertyListIdsMap.get("propValueList");
					String valueId = ValueUtil.toStr(propValueMap.get("valueId"));
					if (ValueUtil.equals(valueId, id)) {
						propertyListIdsMap.put("propValueList", null);
					}

					ProductDetailModel.ProductProperty productProperty = (ProductDetailModel.ProductProperty) MapUtil.mapToObject(propertyListIdsMap, ProductDetailModel.ProductProperty.class);

					productPropertyList.add(productProperty);
				}

				ProductDetailModel productDetailModel = new ProductDetailModel();
				productDetailModel.setProductId(productId);
				productDetailModel.setPropertyListIds(productPropertyList);

				productDetailModelList.add(productDetailModel);
			}
		}

		return productDetailModelList;
	}


}